<template>
    <component :is="tag">
        <slot v-if="pending" name="pending">
            <CommonLoading></CommonLoading>
        </slot>
        <slot v-if="resolved" name="default" v-bind="data"></slot>
        <slot v-if="rejected" name="error" v-bind="error">
            <CommonError :error="error"></CommonError>
        </slot>
    </component>
</template>

<script>
import CommonLoading from './common-loading.vue';
import CommonError from './common-error.vue';

export default {
    name: 'CommonPromise',

    components: { CommonError, CommonLoading },

    props: {
        tag: {
            type: String,
            default: 'div'
        },

        promise: {
            type: Function,
            default: () => {}
        },

        delay: {
            type: [Number, String],
            default: 0
        }
    },

    data() {
        return {
            pending: true,
            started: false,
            resolved: false,
            rejected: false,
            data: null,
            error: null
        };
    },

    computed: {
        delay2() {
            return Math.max(this.delay * 1, 0);
        }
    },

    watch: {
        promise: {
            immediate: true,
            handler(promise) {
                if (promise) {
                    this.start(promise);
                } else {
                    this.stop();
                }
            }
        }
    },

    methods: {
        start(promise) {
            this.wait(() => {
                this.stop();
                promise()
                    .then((data) => {
                        this.pending = false;
                        this.resolved = true;
                        this.data = data;
                    })
                    .catch((err) => {
                        this.pending = false;
                        this.rejected = true;
                        this.error = err;
                    })
                    .finally(() => {
                        this.started = false;
                    });
            });
        },

        stop() {
            this.started = false;
            this.pending = true;
            this.resolved = false;
            this.rejected = false;
            this.data = null;
            this.error = null;
        },

        wait(callback) {
            setTimeout(callback, this.delay2);
        }
    }
};
</script>

<style module lang="scss">
@import '~@isyscore/styles/variables';
</style>
